home *** CD-ROM | disk | FTP | other *** search
- /* memory allocation routines
- *
- * Adapted from alloc routine in K&R; memory statistics and interrupt
- * protection added for use with net package.
- */
-
- #include <stdio.h>
-
- #if (defined(MSC) || defined(__TURBOC__))
- # include <alloc.h>
- #else
- # ifdef M_XENIX
- # include <prototypes.h>
- # else
- extern char *sbrk();
- extern int brk();
- # endif
- #endif
-
- #include "global.h"
- #include "alloc.h"
-
- static long grabbedbytes = 0;
- static unsigned memfail = 0;
- static HEADER base = {&base,1};
- HEADER PTR allocp = &base;
- int need_disable = 0;
-
- /* Define ALLOCDEBUG for allocation recording. Note: works only with
- * small memory model
- */
- #ifdef ALLOCDEBUG
- #define NALLOC 150
- /* Map of allocated memory chunks */
- struct alloc {
- char *addr;
- unsigned size;
- long pc;
- };
- struct alloc alloc[NALLOC];
- #endif
-
- /* Allocate block of 'nb' bytes */
- #ifdef MSDOS
- void *
- #else
- char *
- #endif
- malloc(nb)
- unsigned nb;
- {
- HEADER PTR morecore();
- register HEADER PTR p, PTR q;
- register unsigned nu;
- #ifdef ALLOCDEBUG
- struct alloc *ap;
- unsigned short *ptr;
- #endif
- #ifndef NODISABLE
- char i_state;
-
- if (need_disable)
- i_state = disable();
- #endif
- /* Round up to full block, incl hdr */
- nu = (nb + 2 * sizeof(HEADER) - 1) / sizeof(HEADER);
- if ((q = allocp) == NULLHDR){
- base.s.ptr = allocp = q = &base;
- base.s.size = 1;
- }
- for (p = q->s.ptr; ; q = p, p = p->s.ptr){
- if (p->s.size >= nu){
- /* This chunk is at least as large as we need */
- if (p->s.size == nu){
- /* Perfect fit; remove from list */
- q->s.ptr = p->s.ptr;
- } else {
- /* Carve out piece from end of entry */
- p->s.size -= nu;
- p += p->s.size;
- p->s.size = nu;
- }
- allocp = q;
- p->s.ptr = p; /* for auditing */
- #ifdef ALLOCDEBUG
- for(ap = alloc;ap < &alloc[NALLOC];ap++){
- if(ap->addr == NULLCHAR){
- ap->addr = (char *)(p+1);
- ap->size = nb;
- ptr = &nb;
- #ifdef LARGECODE
- ap->pc = (long)ptr[-1] << 16 +
- (long)ptr[-2];
- #else
- ap->pc = (long)ptr[-1];
- #endif
- break;
- }
- }
- #endif
- #ifndef NODISABLE
- if (need_disable)
- restore(i_state);
- #endif
- return (char *)(p + 1);
- }
- if (p == allocp && (p = morecore(nu)) == NULLHDR){
- memfail++;
- #ifndef NODISABLE
- if (need_disable)
- restore(i_state);
- #endif
- return NULLCHAR;
- }
- }
- }
-
- /* Put memory block back on heap */
- void
- free(blk)
- #ifdef MSDOS
- void *blk;
- #else
- char *blk;
- #endif
- {
- register HEADER PTR p, PTR q;
- unsigned short *ptr;
- #ifdef ALLOCDEBUG
- struct alloc *ap;
- #endif
- #ifndef NODISABLE
- char i_state;
- #endif
-
- if (blk == NULL)
- return;
-
- #ifndef NODISABLE
- if (need_disable)
- i_state = disable();
- #endif
-
- #ifdef ALLOCDEBUG
- for(ap = alloc;ap < &alloc[NALLOC];ap++){
- if(ap->addr == blk){
- ap->addr = NULLCHAR;
- break;
- }
- }
- #endif
- p = (HEADER PTR)blk - 1;
- /* Audit check */
- if(p->s.ptr != p){
- ptr = (unsigned short *)&blk;
- printf("WARNING!! freeing garbage (0x%lx) pc = 0x%04x %04x\n",
- ptr2long(blk),ptr[-1],ptr[-2]);
- fflush(stdout);
- #ifndef NODISABLE
- if (need_disable)
- restore(i_state);
- #endif
- #ifdef Z80
- printf("SP = 0x%04x\n",getsp());
- for(;;) ;
- #else
- return;
- #endif
- }
- /* Search the free list looking for the right place to insert */
- for(q = allocp; !(p > q && p < q->s.ptr); q = q->s.ptr){
- /* Highest address on circular list? */
- if(q >= q->s.ptr && (p > q || p < q->s.ptr))
- break;
- }
- if(p + p->s.size == q->s.ptr){
- /* Combine with front of this entry */
- p->s.size += q->s.ptr->s.size;
- p->s.ptr = q->s.ptr->s.ptr;
- } else {
- /* Link to front of this entry */
- p->s.ptr = q->s.ptr;
- }
- if(q + q->s.size == p){
- /* Combine with end of this entry */
- q->s.size += p->s.size;
- q->s.ptr = p->s.ptr;
- } else {
- /* Link to end of this entry */
- q->s.ptr = p;
- }
- allocp = q;
- #ifndef NODISABLE
- if (need_disable)
- restore(i_state);
- #endif
- }
-
- /* Move existing block to new area */
- #ifdef MSDOS
- void *
- #else
- char *
- #endif
- realloc(area,size)
- #ifdef MSDOS
- void *area;
- #else
- char *area;
- #endif
- unsigned size;
- {
- unsigned osize;
- HEADER PTR hp;
- char *cp;
- #ifndef NODISABLE
- /* Make sure nobody else comes in and takes it */
- char i_state;
-
- if (need_disable)
- i_state = disable();
- #endif
-
- hp = (HEADER PTR)area - 1;
- osize = (hp->s.size -1) * sizeof(HEADER);
-
- free(area);
- if((cp = malloc(size)) != NULLCHAR && cp != area)
- memcpy((char *)cp,(char *)area,size>osize? osize : size);
- #ifndef NODISABLE
- if (need_disable)
- restore(i_state);
- #endif
- return cp;
- }
-
- /* Allocate block of cleared memory */
- #ifdef MSDOS
- void *
- #else
- char *
- #endif
- calloc(nelem,size)
- unsigned nelem; /* Number of elements */
- unsigned size; /* Size of each element */
- {
- register unsigned i;
- register char *cp;
- #ifdef ALLOCDEBUG
- struct alloc *ap;
- short *ptr;
- #endif
- i = nelem * size;
- if((cp = malloc(i)) != NULLCHAR)
- memset(cp,0,i);
- #ifdef ALLOCDEBUG
- if(cp == NULLCHAR)
- return cp;
- /* Adjust caller field to indicate real caller, not calloc() */
- ptr = (short *)&nelem;
- for(ap = alloc; ap < &alloc[NALLOC];ap++)
- if(ap->addr == cp)
- ap->pc = (long)ptr[-1];
- #endif
- return cp;
- }
-
- /* Get more memory from the system and put it on the heap */
- HEADER PTR
- morecore(nu)
- unsigned nu;
- {
- register char *cp;
- register HEADER PTR up;
-
- /* adjust requests for small amounts upward to MIN_ALLOC */
- /* when LARGEDATA, make sure we have one unit extra */
- if (nu < (MIN_ALLOC / sizeof(HEADER)))
- nu = MIN_ALLOC / sizeof(HEADER)
- #ifdef LARGEDATA
- + 1;
- else
- nu++
- #endif
- ;
- if ((int)(cp = sbrk(nu * sizeof(HEADER))) == -1)
- return NULLHDR;
- grabbedbytes += nu * sizeof(HEADER);
- #ifdef LARGEDATA
- /* most C runtimes don't like pointers with offset 0! */
- if ((FP_OFF(cp) % sizeof(HEADER)) == 0){
- cp += 4; /* so move it off the para mark */
- nu--; /* which costs us one unit */
- }
- #endif
- up = (HEADER PTR)cp;
- up->s.size = nu;
- up->s.ptr = up; /* satisfy audit */
- free((char *)(up + 1));
- return allocp;
- }
-
- /* Grab as much memory as possible from the system and put it on the heap */
- void
- grabcore()
- {
- char *cp;
- register HEADER PTR up;
- register unsigned long size;
- #if (defined(MSC) || defined(__TURBOC__))
- char redzone[4096];
- #endif
-
- /* Find out where the break is */
- cp = sbrk(0);
- /* Now try to push it as high as possible */
- #if (defined(MSC) || defined(__TURBOC__))
- redzone[0] = size = 0;
- while(sbrk(256) != (char *)(-1)) {
- size += 256;
- # ifdef LARGEDATA
- if (size > 32000)
- break;
- # endif
- }
- #else
- for(size=256; size < 65535-256;size += 256){
- if(brk((char *) (cp + size)) == -1){
- size -= 256;
- break;
- }
- }
- #endif
- grabbedbytes += size;
- #ifdef LARGEDATA
- /* most C runtimes don't like pointers with offset 0! */
- if ((FP_OFF(cp) % sizeof(HEADER)) == 0){
- cp += 4; /* so move it off the para mark */
- size -= 4;
- }
- #endif
- up = (HEADER PTR)cp;
- up->s.size = size / sizeof(HEADER);
- up->s.ptr = up; /* satisfy audit */
- free((char *)(up + 1));
- }
-
- #ifndef NOMEMSTAT
- /* Print free list map */
- memstat(argc,argv)
- int argc;
- char *argv[];
- {
- HEADER PTR p;
- unsigned long totalfree;
-
- totalfree = 0;
- p = &base;
- do {
- totalfree += (unsigned long) p->s.size * sizeof(HEADER);
- if (argc != 1){
- printf("%*lx %lu",2*sizeof(p),ptr2long(p),
- (unsigned long) p->s.size * sizeof(HEADER));
- if(p == allocp)
- printf(" <-- allocp\n");
- else
- printf("\n");
- }
- p = p->s.ptr;
- } while(p != &base);
- printf("Total: %lu bytes grabbed, %lu bytes free\n",
- grabbedbytes,totalfree);
- #ifdef ALLOCDEBUG
- if (argc != 1) {
- struct alloc *ap;
- printf("addr size caller\n");
- for(ap = alloc;ap < &alloc[NALLOC];ap++){
- if(ap->addr != NULLCHAR)
- printf("0x%-8lx%-10d %08lx\n",
- ptr2long(ap->addr),ap->size,ap->pc);
- }
- }
- #endif
- printf("malloc fails %u\n",memfail);
- fflush(stdout);
- return 0;
- }
- #endif
-